跳到主要内容

类何时会被加载

先来看第一个问题:如果一个类没有在程序中的任何地方被使用,它会被加载吗?

答案是:不会!

如果一个类没有在任何地方使用它是不会被类加装器加载的。哪怕是在代码中通过 import 引入,也不会被类加载器加载。

跟踪类的加载

如何判断一个类是否被类加装器加载?

我们可以通过 -verbose:class 来跟踪类的加加载情况,这个参数会输出类加载的详细信息到标准输出或日志文件中。

来看一个具体的实例:

package tech.devguide.reflection.classload.model

public class User {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
java

只通过 import 引入,不使用的情况:

package tech.devguide.reflection.classload;

import tech.devguide.reflection.classload.model.User;

public class ClassLoadTest {

public static void main(String[] args) {
System.out.println("Hello world");
}
}
java

控制台日志(仅过滤 tech.devguide 包下的加装记录):

[0.115s][info][class,load] tech.devguide.reflection.classload.ClassLoadTest source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
Hello world
text

修改上面的方法,在 main() 方法中创建一个 User 实例。

package tech.devguide.reflection.classload;

import tech.devguide.reflection.classload.model.User;

public class ClassLoadTest {

public static void main(String[] args) {
System.out.println("Hello world");
User user = new User();
}
}
java

然后再观察控制台日志:

[0.096s][info][class,load] tech.devguide.reflection.classload.ClassLoadTest source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
Hello world
[0.097s][info][class,load] tech.devguide.reflection.classload.model.User source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
text

由此可以判断,类是在使用的时候才被加载的。

跟反射的关系

反射是在程序运行时动态的创建类或者调用对象的方法。也就是说,如果通过反射动态的来创建一个类,那这个类的加载过程将发生在反射处理阶段。

package tech.devguide.reflection.classload;

import tech.devguide.reflection.classload.model.User;

public class ClassLoadTest {

public static void main(String[] args) {
System.out.println("Hello world");
Class.forName("tech.devguide.reflection.classload.model.User");
}
}
java

控制台日志:

[0.127s][info][class,load] tech.devguide.reflection.classload.ClassLoadTest source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
Hello world
[0.128s][info][class,load] tech.devguide.reflection.classload.model.User source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/

这里是我们需要注意的一个点,当我们使用反射来实例化一个类,或者获取类信息时,如果类并没有被加载,会有一个类加载的过程。

但是当我们在讨论反射的性能时,这个过程并不能计算在内。因为当我们第一次创建某个对象的实例时,同样也会有类加载的过程。